package com.example.friend.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.example.common.core.constants.JwtConstants;
import com.example.common.core.domain.ResultCode;
import com.example.common.core.enums.UserIdentity;
import com.example.friend.config.ThreadPoolUtil;
import com.example.friend.domain.user.User;
import com.example.friend.domain.user.dto.UserDTO;
import com.example.friend.mapper.user.UserMapper;
import com.example.friend.service.IUserService;
import com.example.security.exception.ServiceException;
import com.example.security.service.TokenService;
import jakarta.mail.MessagingException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import com.example.service.RedisService;

import java.util.Date;
import java.util.concurrent.TimeUnit;


/**
 * LTAI5tKDiC7uJ4GgyYysj4jB
 * TD6CNtJ6Md1yLCRXreinKyteMQjF1u
 * <p>
 * qocoavfdgtnodgdg
 */

@Service
@Slf4j
public class IUserServiceImpl implements IUserService {
    /**
     * 注入邮件工具类
     */
    @Autowired
    private JavaMailSenderImpl javaMailSender;

    @Autowired
    private RedisService redisService;

    @Autowired
    private TokenService tokenService;

    @Autowired
    private UserMapper userMapper;


    private String secret = JwtConstants.LOGIN_USER_KEY;

    @Value("${spring.mail.username}")
    private String sendMailer;

    @Value("${sms.mail.code-expiration:2}")
    private Long codeExpiration;

    @Value("${sms.mail.max-code-count:100}")
    private Long maxCodeCount;

    @Value("${sms.mail.get-code-count-expiration:1}")
    private Long codeCountExpiration;

    /***
     *
     * @param userDTO
     */
    @Override
    public void sentCode(UserDTO userDTO) {
        // 1. 校验邮箱合法性（原有逻辑）
        if (userDTO.getEmail() == null || !StringUtils.hasText(userDTO.getEmail())
                || !Validator.isEmail(userDTO.getEmail())) {
            throw new ServiceException(ResultCode.ILLEGAL_EMAIl);
        }

        // 2. 校验验证码发送频率（原有逻辑）
        Long cacheObject = redisService.getCacheObject("p:c" + userDTO.getEmail(), Long.class);
        if (cacheObject != null && cacheObject > 0) {
            if (cacheObject > maxCodeCount) {
                throw new ServiceException(ResultCode.FAILED_GET_CODE_LIMIT);
            }
            redisService.increment("p:c" + userDTO.getEmail());
        } else {
            redisService.setCacheObject("p:c" + userDTO.getEmail(), 1, codeCountExpiration, TimeUnit.DAYS);
        }

        // 3. 生成验证码并缓存（原有逻辑）
        String code = RandomUtil.randomNumbers(6);
        redisService.setCacheObject(getEmailKey(userDTO.getEmail()), code, codeExpiration, TimeUnit.MINUTES);

        // 4. 异步发送邮件（关键修改：提交到线程池）
        ThreadPoolUtil.submitMailTask(() -> {
            try {
                sendTextMailMessage(userDTO.getEmail(), "欢迎注册-鸾章题舍-在线OJ系统，",
                        "尊敬的用户，您的验证码是：" + code + "，有效期时间为：" + codeExpiration + "分钟" + "，请在有效时间内完成注册");
            } catch (Exception e) {
                // 记录邮件发送失败的日志（避免线程内异常被吞）
                log.error("邮件发送失败，邮箱：{}", userDTO.getEmail(), e);
            }
        });
    }

    @Override
    public String login(UserDTO userDTO) {
        User user = userMapper.selectOne(new LambdaQueryWrapper<User>()
                .eq(User::getEmail, userDTO.getEmail()));
        String key = getEmailKey(userDTO.getEmail());
        String cacheCode = redisService.getCacheObject(key, String.class);
        log.info("cacheCode:{}", cacheCode);
        if (!StringUtils.hasText(cacheCode)) {
            throw new ServiceException(ResultCode.VALID_CODE);
        }
        if (!userDTO.getCode().equals(cacheCode)) {
            throw new ServiceException(ResultCode.ERROR_CODE);
        }
        redisService.deleteObject(key);
        if (user == null) {
            User insert = new User();
            BeanUtil.copyProperties(userDTO, insert);
            int insertRet = userMapper.insert(insert);
            if (insertRet != 1) {
                throw new ServiceException(ResultCode.FAILED);
            }
        }
        log.info("secret:{}", secret);
        return tokenService.createToken(user.getUserId(), secret, UserIdentity.ORDINARY.getValue(), user.getNickName(), user.getHeadImage());

    }

    private String getEmailKey(String email) {
        return "p:e" + email;
    }

    /**
     * 检测邮件信息类
     *
     * @param to
     * @param subject
     * @param text
     */
    private void checkMail(String to, String subject, String text) {
        if (StringUtils.isEmpty(to)) {
            throw new RuntimeException("邮件收信人不能为空");
        }
        if (StringUtils.isEmpty(subject)) {
            throw new RuntimeException("邮件主题不能为空");
        }
        if (StringUtils.isEmpty(text)) {
            throw new RuntimeException("邮件内容不能为空");
        }
    }

    /**
     * 发送纯文本邮件
     *
     * @param to
     * @param subject
     * @param text
     */
    public void sendTextMailMessage(String to, String subject, String text) {

        try {
            //true 代表支持复杂的类型
            MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(javaMailSender.createMimeMessage(), true);
            //邮件发信人
            mimeMessageHelper.setFrom(sendMailer);
            //邮件收信人  1或多个
            mimeMessageHelper.setTo(to.split(","));
            //邮件主题
            mimeMessageHelper.setSubject(subject);
            //邮件内容
            mimeMessageHelper.setText(text);
            //邮件发送时间
            mimeMessageHelper.setSentDate(new Date());

            //发送邮件
            javaMailSender.send(mimeMessageHelper.getMimeMessage());
            System.out.println("发送邮件成功：" + sendMailer + "->" + to);

        } catch (MessagingException e) {
            e.printStackTrace();
            System.out.println("发送邮件失败：" + e.getMessage());
        }
    }
}
